﻿goog.provide('ol.dmp.PoltEvent');
goog.provide('ol.dmp.PoltInteraction');

goog.require('goog.asserts');
goog.require('goog.events.Event');
goog.require('ol.Collection');
goog.require('ol.Coordinate');
goog.require('ol.Feature');
goog.require('ol.FeatureOverlay');
goog.require('ol.Map');
goog.require('ol.MapBrowserEvent');
goog.require('ol.MapBrowserEvent.EventType');
goog.require('ol.events.condition');
goog.require('ol.feature');
goog.require('ol.geom.GeometryType');
goog.require('ol.geom.LineString');
goog.require('ol.geom.MultiLineString');
goog.require('ol.geom.MultiPoint');
goog.require('ol.geom.MultiPolygon');
goog.require('ol.geom.Point');
goog.require('ol.geom.Polygon');
goog.require('ol.interaction.Pointer');
goog.require('ol.source.Vector');
goog.require('ol.dmp.algorithmsUtility');
goog.require('ol.dmp.interactionGeometry.featureFactory');


ol.dmp.PoltEventType = {

    DRAWSTART: 'drawstart',

    DRAWEND: 'drawend'
};


ol.dmp.PoltKeyFeature = function (options)
{
    this.name = goog.isDef(options.name) ? options.name : "name1";

    this.keyPoints=goog.isDef(options.keypoints)?options.keypoints:[];
};



ol.dmp.PoltEvent = function (type, feature,keyFeature)
{

    goog.base(this, type);

    /**
     * The feature being drawn.
     * @type {ol.Feature}
     * @api stable
     */
    this.feature = feature;

    // 记录图元关键点的要素，还包含要素名称，
    this.keyFeature = keyFeature;
};
goog.inherits(ol.dmp.PoltEvent, goog.events.Event);


ol.dmp.PoltInteraction = function (options)
{

    goog.base(this);

    /**
     * @type {ol.Pixel}
     * @private
     */
    this.downPx_ = null;

    /**
     * Target source for drawn features.
     * @type {ol.source.Vector}
     * @private
     */
    this.source_ = goog.isDef(options.source) ? options.source : null;

    /**
     * Target collection for drawn features.
     * @type {ol.Collection}
     * @private
     */
    this.features_ = goog.isDef(options.features) ? options.features : [];


    /// 要素交互对象
    this.featureBase_ = ol.dmp.interactionGeometry.featureFactory(options.type);

    /**
     * Finish coordinate for the feature (first point for polygons, last point for
     * linestrings).
     * @type {ol.Coordinate}
     * @private
     */
    this.finishCoordinate_ = null;

    /**
     * Sketch feature.
     * @type {ol.Feature}
     * @private
     */
    this.sketchFeature_ = null;

    /**
     * Sketch point.
     * @type {ol.Feature}
     * @private
     */
    this.sketchPoint_ = null;

    /**
     * Sketch line. Used when drawing polygon.
     * @type {ol.Feature}
     * @private
     */
    this.sketchLine_ = null;


    /**
     * Squared tolerance for handling up events.  If the squared distance
     * between a down and up event is greater than this tolerance, up events
     * will not be handled.
     * @type {number}
     * @private
     */
    this.squaredClickTolerance_ = 4;

    /**
     * Draw overlay where are sketch features are drawn.
     * @type {ol.FeatureOverlay}
     * @private
     */
    this.overlay_ = new ol.FeatureOverlay({
        style: goog.isDef(options.style) ?
            options.style : ol.dmp.PoltInteraction.getDefaultStyleFunction()
    });

    /**
     * Name of the geometry attribute for newly created features.
     * @type {string|undefined}
     * @private
     */
    this.geometryName_ = options.geometryName;

    /**
     * @private
     * @type {ol.events.ConditionType}
     */
    this.condition_ = goog.isDef(options.condition) ?
        options.condition : ol.events.condition.noModifierKeys;

};

goog.inherits(ol.dmp.PoltInteraction, ol.interaction.Pointer);

ol.dmp.PoltInteraction.getDefaultStyleFunction = function ()
{
    var styles = ol.feature.createDefaultEditingStyles();
    return function (feature, resolution)
    {
        return styles[feature.getGeometry().getType()];
    };
};

/**
 * @inheritDoc
 */
ol.dmp.PoltInteraction.prototype.setMap = function (map)
{
    if (goog.isNull(map))
    {
        // removing from a map, clean up
        this.abortDrawing_();
    }
    this.overlay_.setMap(map);
    goog.base(this, 'setMap', map);
};

/**
 * @inheritDoc
 */
ol.dmp.PoltInteraction.prototype.handleMapBrowserEvent = function (event)
{
    var map = event.map;
    if (!map.isDef())
    {
        return true;
    }
    var pass = true;
    if (event.type === ol.MapBrowserEvent.EventType.POINTERMOVE)
    {
        pass = this.handlePointerMove_(event);
    }
    else if (event.type === ol.MapBrowserEvent.EventType.DBLCLICK)
    {
        pass = false;
    }
    return (goog.base(this, 'handleMapBrowserEvent', event) && pass);
};

/**
 * Handle down events.
 * @param {ol.MapBrowserEvent} event A down event.
 * @return {boolean} Pass the event to other interactions.
 */
ol.dmp.PoltInteraction.prototype.handlePointerDown = function (event)
{
    if (this.condition_(event))
    {
        this.downPx_= event.pixel;
        return true;
    }
    else
    {
        return false;
    }
};


/**
 * Handle up events.
 * @param {ol.MapBrowserEvent} event An up event.
 * @return {boolean} Pass the event to other interactions.
 */
ol.dmp.PoltInteraction.prototype.handlePointerUp = function (event)
{
    if (goog.isNull(this.featureBase_))
    {
        return true;
    }

    var downPx = this.downPx_;
    var clickPx = event.pixel;
    var dx = downPx[0] - clickPx[0];
    var dy = downPx[1] - clickPx[1];
    var squaredDistance = dx * dx + dy * dy;
    var pass = true;
    if (squaredDistance <= this.squaredClickTolerance_)       // 判断是否是原地抬起了鼠标,也就是是否是单击事件
    {
        this.handlePointerMove_(event);

        if (this.featureBase_.atFinish(event))              // 
        {
            this.finishDrawing_(event);
        }
        else
        {
            if (goog.isNull(this.finishCoordinate_))              // 如果 this.finishCoordinate为空，则代表新的绘制开始
            {
                this.startDrawing_(event);
            }
            else
            {
                this.addToDrawing_(event);
            }
        }

        pass = false;
    }
    return pass;
};


/**
 * Handle move events.
 * @param {ol.MapBrowserEvent} event A move event.
 * @return {boolean} Pass the event to other interactions.
 * @private
 */
ol.dmp.PoltInteraction.prototype.handlePointerMove_ = function (event)
{
    if (goog.isNull(this.featureBase_))
    {
        return true;
    }
    
    if (!goog.isNull(this.finishCoordinate_))
    {
        this.modifyDrawing_(event);
    }

    this.createOrUpdateSketchPoint_(event);
    return true;
};


/**
 * 确定一个顶点是否和此要素上的开始点重合   // 绘制多边形时用途较大  // 或者其他可以结束绘制的用途
 * Determine if an event is within the snapping tolerance of the start coord.   
 * @param {ol.MapBrowserEvent} event Event.
 * @return {boolean} The event is within the snapping tolerance of the start.
 * @private
 */
ol.dmp.PoltInteraction.prototype.atFinish_ = function (event)
{
    if (goog.isDef(this.featureBase_))
    {
        return this.featureBase_.atFinish(event);
    }

    return true;
};


/**
 * @param {ol.MapBrowserEvent} event Event.
 * @private
 */
ol.dmp.PoltInteraction.prototype.createOrUpdateSketchPoint_ = function (event)
{

    if (goog.isDef(this.featureBase_))
    {
        this.featureBase_.createOrUpdateSketchPoint(event);

        var sketchPoint= this.featureBase_.getSketchPoint();
        
        if (goog.isNull(this.sketchPoint_))
        {
            this.sketchPoint_ =sketchPoint;
            this.updateSketchFeatures_();
        }
        else
        {
            this.sketchPoint_.setGeometry(sketchPoint.getGeometry());
        }
    }
};


/**
 * Start the drawing.
 * @param {ol.MapBrowserEvent} event Event.
 * @private
 */
ol.dmp.PoltInteraction.prototype.startDrawing_ = function (event)
{

    this.finishCoordinate_ = event.coordinate;

    if (goog.isDef(this.featureBase_))
    {
        this.featureBase_.startDrawing(event);
        this.sketchFeature_ = this.featureBase_.getSketchFeature();
    }

    this.updateSketchFeatures_();
    this.dispatchEvent(new ol.DrawEvent(ol.DrawEventType.DRAWSTART,
        this.sketchFeature_));
};


/**
 * Modify the drawing.
 * @param {ol.MapBrowserEvent} event Event.
 * @private
 */
ol.dmp.PoltInteraction.prototype.modifyDrawing_ = function (event)
{
 
    if (goog.isDef(this.featureBase_))
    {
        this.featureBase_.modifyDrawing(event);

        this.sketchLine_ = this.featureBase_.getSketchLine();
        this.sketchFeature_ = this.featureBase_.getSketchFeature();
    }

    this.updateSketchFeatures_();
};


/**
 * Add a new coordinate to the drawing.
 * @param {ol.MapBrowserEvent} event Event.
 * @private
 */
ol.dmp.PoltInteraction.prototype.addToDrawing_ = function (event)
{

    if (goog.isDef(this.featureBase_))
    {
        this.featureBase_.addToDrawing(event);

        this.sketchLine_ = this.featureBase_.getSketchLine();
        this.sketchFeature_ = this.featureBase_.getSketchFeature();
    }
    this.updateSketchFeatures_();
};


/**
 * Stop drawing and add the sketch feature to the target layer.
 * @param {ol.MapBrowserEvent} event Event.
 * @private
 */
ol.dmp.PoltInteraction.prototype.finishDrawing_ = function (event)
{

    if (goog.isDef(this.featureBase_))
    {
        this.featureBase_.finishDrawing(event);
        var sketchFeature = this.abortDrawing_();
        if (!goog.isNull(this.features_))
        {
            this.features_.push(sketchFeature.feature);
        }
        if (!goog.isNull(this.source_))
        {
            this.source_.addFeature(sketchFeature.feature);
        }
        this.dispatchEvent(new ol.dmp.PoltEvent(ol.dmp.PoltEventType.DRAWEND, sketchFeature.feature, new ol.dmp.PoltKeyFeature( {keypoints:sketchFeature.keypoints})));
    }


};


/**
 * Stop drawing without adding the sketch feature to the target layer.
 * @return {ol.Feature} The sketch feature (or null if none).
 * @private
 */
ol.dmp.PoltInteraction.prototype.abortDrawing_ = function ()
{
    this.finishCoordinate_ = null;
    var sketchFeature = this.featureBase_.abortDrawing();
    if (!goog.isNull(sketchFeature))
    {
        this.sketchFeature_ = null;
        this.sketchPoint_ = null;
        this.sketchLine_ = null;
        this.overlay_.getFeatures().clear();
    }
    return sketchFeature;
};


/**
 * Redraw the skecth features.
 * @private
 */
ol.dmp.PoltInteraction.prototype.updateSketchFeatures_ = function ()
{
    var sketchFeatures = [];
    if (!goog.isNull(this.sketchFeature_))
    {
        sketchFeatures.push(this.sketchFeature_);
    }
    if (!goog.isNull(this.sketchLine_))
    {
        sketchFeatures.push(this.sketchLine_);
    }
    if (!goog.isNull(this.sketchPoint_))
    {
        sketchFeatures.push(this.sketchPoint_);
    }
    this.overlay_.setFeatures(new ol.Collection(sketchFeatures));
};



ol.dmp.PoltInteraction.prototype.setFeatureType=function(type)
{
    this.featureBase_ = ol.dmp.interactionGeometry.featureFactory(type);
};


ol.dmp.PoltInteraction.prototype.getFeatures = function ()
{
    return this.features_;
}